package com.core.cloudcommon.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author =====Lqj=====
 * @className SnowflakeIdGenerator
 * @description 雪花算法ID生成器 - 按模块分配不同的机器码
 * @create 2024/12/17 10:30
 **/
@Slf4j
@Component
public class SnowflakeIdGenerator {

    /**
     * 雪花算法各部分位数
     */
    private static final long WORKER_ID_BITS = 5L;        // 机器ID位数
    private static final long DATACENTER_ID_BITS = 5L;    // 数据中心ID位数
    private static final long SEQUENCE_BITS = 12L;        // 序列号位数

    /**
     * 各部分最大值
     */
    private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);           // 最大机器ID: 31
    private static final long MAX_DATACENTER_ID = ~(-1L << DATACENTER_ID_BITS);   // 最大数据中心ID: 31
    private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);             // 最大序列号: 4095

    /**
     * 各部分位移
     */
    private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;                                    // 12
    private static final long DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;              // 17
    private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS; // 22

    /**
     * 起始时间戳 (2024-01-01 00:00:00)
     */
    private static final long START_TIMESTAMP = 1704067200000L;

    /**
     * 数据中心ID (固定为1)
     */
    private static final long DATACENTER_ID = 1L;

    /**
     * 模块机器码枚举
     */
    public enum ModuleCode {
        // 系统模块 (1-10)
        SYSTEM_USER(1, "系统用户模块"),
        SYSTEM_DEPART(2, "系统部门模块"),
        SYSTEM_LOGIN(3, "系统登录模块"),
        SYSTEM_LOG(4, "系统日志模块"),
        SYSTEM_DEVICE(5, "设备管理模块"),
        SYSTEM_SECURITY(6, "安全管理模块"),
        SYSTEM_CONFIG(7, "系统配置模块"),
        SYSTEM_DICT(8, "数据字典模块"),
        SYSTEM_OPERATION(9, "操作日志模块"),
        SYSTEM_COMMON(10, "系统通用模块"),

        // 工单模块 (11-20)
        SHEET_MAYOR(11, "12345工单模块"),
        SHEET_NETWORK(12, "网络工单模块"),
        SHEET_LETTERS(13, "信访工单模块"),
        SHEET_PROCESS(14, "工单流程模块"),
        SHEET_ATTACHMENT(15, "工单附件模块"),
        SHEET_STATISTICS(16, "工单统计模块"),
        SHEET_COMMON(17, "工单通用模块"),

        // 网关模块 (21-25)
        GATEWAY_AUTH(21, "网关认证模块"),
        GATEWAY_ROUTE(22, "网关路由模块"),
        GATEWAY_FILTER(23, "网关过滤模块"),
        GATEWAY_LIMIT(24, "网关限流模块"),
        GATEWAY_LOG(25, "网关日志模块"),

        // 开放接口模块 (26-30)
        OPEN_API(26, "开放接口模块"),
        OPEN_AUTH(27, "开放认证模块"),
        OPEN_LOG(28, "开放日志模块"),
        OPEN_LIMIT(29, "开放限流模块"),
        OPEN_COMMON(30, "开放通用模块"),

        // 预留模块 (31)
        RESERVED(31, "预留模块");

        private final long code;
        private final String description;

        ModuleCode(long code, String description) {
            this.code = code;
            this.description = description;
        }

        public long getCode() {
            return code;
        }

        public String getDescription() {
            return description;
        }
    }

    /**
     * 雪花算法实例缓存
     */
    private static final ConcurrentHashMap<Long, Snowflake> SNOWFLAKE_CACHE = new ConcurrentHashMap<>();

    /**
     * 雪花算法核心类
     */
    private static class Snowflake {
        private final long workerId;
        private final long datacenterId;
        private long sequence = 0L;
        private long lastTimestamp = -1L;

        public Snowflake(long workerId, long datacenterId) {
            if (workerId > MAX_WORKER_ID || workerId < 0) {
                throw new IllegalArgumentException(String.format("Worker ID 必须在 0 到 %d 之间", MAX_WORKER_ID));
            }
            if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) {
                throw new IllegalArgumentException(String.format("Datacenter ID 必须在 0 到 %d 之间", MAX_DATACENTER_ID));
            }
            this.workerId = workerId;
            this.datacenterId = datacenterId;
        }

        public synchronized long nextId() {
            long timestamp = timeGen();

            // 时钟回拨检查
            if (timestamp < lastTimestamp) {
                throw new RuntimeException(String.format("时钟回拨，拒绝生成ID，时间差: %d ms", lastTimestamp - timestamp));
            }

            // 同一毫秒内，序列号递增
            if (lastTimestamp == timestamp) {
                sequence = (sequence + 1) & MAX_SEQUENCE;
                // 序列号溢出，等待下一毫秒
                if (sequence == 0) {
                    timestamp = tilNextMillis(lastTimestamp);
                }
            } else {
                // 不同毫秒，序列号重置
                sequence = 0L;
            }

            lastTimestamp = timestamp;

            // 生成ID
            return ((timestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT)
                    | (datacenterId << DATACENTER_ID_SHIFT)
                    | (workerId << WORKER_ID_SHIFT)
                    | sequence;
        }

        /**
         * 等待下一毫秒
         */
        private long tilNextMillis(long lastTimestamp) {
            long timestamp = timeGen();
            while (timestamp <= lastTimestamp) {
                timestamp = timeGen();
            }
            return timestamp;
        }

        /**
         * 获取当前时间戳
         */
        private long timeGen() {
            return System.currentTimeMillis();
        }
    }

    /**
     * 获取指定模块的雪花算法实例
     */
    private Snowflake getSnowflake(ModuleCode moduleCode) {
        return SNOWFLAKE_CACHE.computeIfAbsent(moduleCode.getCode(), 
            workerId -> new Snowflake(workerId, DATACENTER_ID));
    }

    /**
     * 生成指定模块的ID
     * @param moduleCode 模块代码
     * @return 雪花ID
     */
    public long generateId(ModuleCode moduleCode) {
        try {
            long id = getSnowflake(moduleCode).nextId();
            log.debug("生成雪花ID: {} (模块: {})", id, moduleCode.getDescription());
            return id;
        } catch (Exception e) {
            log.error("生成雪花ID失败，模块: {}, 错误: {}", moduleCode.getDescription(), e.getMessage());
            throw new RuntimeException("生成雪花ID失败", e);
        }
    }

    /**
     * 生成系统用户模块ID
     */
    public long generateSystemUserId() {
        return generateId(ModuleCode.SYSTEM_USER);
    }

    /**
     * 生成系统部门模块ID
     */
    public long generateSystemDepartId() {
        return generateId(ModuleCode.SYSTEM_DEPART);
    }

    /**
     * 生成系统登录模块ID
     */
    public long generateSystemLoginId() {
        return generateId(ModuleCode.SYSTEM_LOGIN);
    }

    /**
     * 生成系统日志模块ID
     */
    public long generateSystemLogId() {
        return generateId(ModuleCode.SYSTEM_LOG);
    }

    /**
     * 生成设备管理模块ID
     */
    public long generateSystemDeviceId() {
        return generateId(ModuleCode.SYSTEM_DEVICE);
    }

    /**
     * 生成安全管理模块ID
     */
    public long generateSystemSecurityId() {
        return generateId(ModuleCode.SYSTEM_SECURITY);
    }

    /**
     * 生成12345工单模块ID
     */
    public long generateSheetMayorId() {
        return generateId(ModuleCode.SHEET_MAYOR);
    }

    /**
     * 生成网络工单模块ID
     */
    public long generateSheetNetworkId() {
        return generateId(ModuleCode.SHEET_NETWORK);
    }

    /**
     * 生成信访工单模块ID
     */
    public long generateSheetLettersId() {
        return generateId(ModuleCode.SHEET_LETTERS);
    }

    /**
     * 生成工单流程模块ID
     */
    public long generateSheetProcessId() {
        return generateId(ModuleCode.SHEET_PROCESS);
    }

    /**
     * 生成工单附件模块ID
     */
    public long generateSheetAttachmentId() {
        return generateId(ModuleCode.SHEET_ATTACHMENT);
    }

    /**
     * 生成网关认证模块ID
     */
    public long generateGatewayAuthId() {
        return generateId(ModuleCode.GATEWAY_AUTH);
    }

    /**
     * 生成开放接口模块ID
     */
    public long generateOpenApiId() {
        return generateId(ModuleCode.OPEN_API);
    }

    /**
     * 解析雪花ID，获取各部分信息
     * @param id 雪花ID
     * @return 解析结果
     */
    public SnowflakeInfo parseSnowflakeId(long id) {
        // 提取时间戳
        long timestamp = (id >> TIMESTAMP_LEFT_SHIFT) + START_TIMESTAMP;
        
        // 提取数据中心ID
        long datacenterId = (id >> DATACENTER_ID_SHIFT) & MAX_DATACENTER_ID;
        
        // 提取机器ID
        long workerId = (id >> WORKER_ID_SHIFT) & MAX_WORKER_ID;
        
        // 提取序列号
        long sequence = id & MAX_SEQUENCE;

        // 查找对应的模块
        ModuleCode moduleCode = null;
        for (ModuleCode code : ModuleCode.values()) {
            if (code.getCode() == workerId) {
                moduleCode = code;
                break;
            }
        }

        return new SnowflakeInfo(id, timestamp, datacenterId, workerId, sequence, moduleCode);
    }

    /**
     * 雪花ID解析结果
     */
    public static class SnowflakeInfo {
        private final long id;
        private final long timestamp;
        private final long datacenterId;
        private final long workerId;
        private final long sequence;
        private final ModuleCode moduleCode;

        public SnowflakeInfo(long id, long timestamp, long datacenterId, long workerId, 
                           long sequence, ModuleCode moduleCode) {
            this.id = id;
            this.timestamp = timestamp;
            this.datacenterId = datacenterId;
            this.workerId = workerId;
            this.sequence = sequence;
            this.moduleCode = moduleCode;
        }

        // Getters
        public long getId() { return id; }
        public long getTimestamp() { return timestamp; }
        public long getDatacenterId() { return datacenterId; }
        public long getWorkerId() { return workerId; }
        public long getSequence() { return sequence; }
        public ModuleCode getModuleCode() { return moduleCode; }

        @Override
        public String toString() {
            return String.format("SnowflakeInfo{id=%d, timestamp=%d, datacenterId=%d, workerId=%d, sequence=%d, module=%s}", 
                id, timestamp, datacenterId, workerId, sequence, 
                moduleCode != null ? moduleCode.getDescription() : "未知模块");
        }
    }

    /**
     * 获取模块统计信息
     */
    public String getModuleStatistics() {
        StringBuilder sb = new StringBuilder();
        sb.append("雪花ID生成器模块统计:\n");
        sb.append("数据中心ID: ").append(DATACENTER_ID).append("\n");
        sb.append("已初始化的模块数量: ").append(SNOWFLAKE_CACHE.size()).append("\n");
        sb.append("模块详情:\n");
        
        for (ModuleCode moduleCode : ModuleCode.values()) {
            if (SNOWFLAKE_CACHE.containsKey(moduleCode.getCode())) {
                sb.append("  - ").append(moduleCode.getDescription())
                  .append(" (机器码: ").append(moduleCode.getCode()).append(") [已初始化]\n");
            } else {
                sb.append("  - ").append(moduleCode.getDescription())
                  .append(" (机器码: ").append(moduleCode.getCode()).append(") [未使用]\n");
            }
        }
        
        return sb.toString();
    }
}
